/**
 * 统一结构化日志系统
 * EndoSight-UC 医疗AI系统
 *
 * 提供医疗级结构化日志记录和审计追踪功能
 */

import winston from 'winston';
import fs from 'fs';
import path from 'path';
import crypto from 'crypto';

// 日志级别定义
const LogLevel = {
  CRITICAL: 'critical',    // 系统严重错误，可能影响生命安全
  ERROR: 'error',          // 系统错误，影响功能
  WARNING: 'warning',      // 警告信息，需要关注
  INFO: 'info',            // 一般信息
  DEBUG: 'debug',          // 调试信息
  AUDIT: 'audit',          // 审计日志，不可修改
  SECURITY: 'security',    // 安全事件，需要立即关注
  COMPLIANCE: 'compliance' // 合规相关日志
};

// 审计事件类型
const AuditEventType = {
  // 用户相关事件
  USER_LOGIN: 'user_login',
  USER_LOGOUT: 'user_logout',
  USER_REGISTER: 'user_register',
  USER_PASSWORD_CHANGE: 'user_password_change',
  USER_PROFILE_UPDATE: 'user_profile_update',

  // 认证相关事件
  AUTH_SUCCESS: 'auth_success',
  AUTH_FAILURE: 'auth_failure',
  TOKEN_ISSUED: 'token_issued',
  TOKEN_REFRESHED: 'token_refreshed',
  TOKEN_EXPIRED: 'token_expired',

  // 患者数据相关事件
  PATIENT_CREATE: 'patient_create',
  PATIENT_VIEW: 'patient_view',
  PATIENT_UPDATE: 'patient_update',
  PATIENT_DELETE: 'patient_delete',
  PATIENT_EXPORT: 'patient_export',

  // 医疗图像相关事件
  IMAGE_UPLOAD: 'image_upload',
  IMAGE_VIEW: 'image_view',
  IMAGE_DELETE: 'image_delete',
  IMAGE_ANALYZE: 'image_analyze',
  IMAGE_PROCESS: 'image_process',

  // AI推理相关事件
  AI_INFERENCE_REQUEST: 'ai_inference_request',
  AI_INFERENCE_SUCCESS: 'ai_inference_success',
  AI_INFERENCE_FAILURE: 'ai_inference_failure',
  AI_MODEL_CHANGE: 'ai_model_change',
  AI_RESULT_VIEW: 'ai_result_view',

  // 评分相关事件
  SCORING_TASK_CREATE: 'scoring_task_create',
  SCORING_TASK_UPDATE: 'scoring_task_update',
  SCORING_RESULT_CREATE: 'scoring_result_create',
  SCORING_RESULT_VIEW: 'scoring_result_view',
  SCORING_RESULT_MODIFY: 'scoring_result_modify',

  // 系统管理事件
  SYSTEM_CONFIG_CHANGE: 'system_config_change',
  SYSTEM_BACKUP: 'system_backup',
  SYSTEM_RESTORE: 'system_restore',
  SYSTEM_MAINTENANCE: 'system_maintenance',

  // 数据管理事件
  DATA_EXPORT: 'data_export',
  DATA_IMPORT: 'data_import',
  DATA_PURGE: 'data_purge',
  DATA_ARCHIVE: 'data_archive',

  // 安全相关事件
  SECURITY_BREACH: 'security_breach',
  SECURITY_VIOLATION: 'security_violation',
  PRIVILEGE_ESCALATION: 'privilege_escalation',
  UNAUTHORIZED_ACCESS: 'unauthorized_access',

  // 合规相关事件
  COMPLIANCE_CHECK: 'compliance_check',
  COMPLIANCE_VIOLATION: 'compliance_violation',
  AUDIT_TRAIL_ACCESS: 'audit_trail_access',
  CONSENT_RECORD: 'consent_record'
};

// PHI数据类型
const PHIDataType = {
  PATIENT_NAME: 'patient_name',
  PATIENT_ID: 'patient_id',
  MEDICAL_RECORD: 'medical_record',
  DIAGNOSIS: 'diagnosis',
  TREATMENT: 'treatment',
  PRESCRIPTION: 'prescription',
  LAB_RESULTS: 'lab_results',
  IMAGING_RESULTS: 'imaging_results',
  CLINICAL_NOTES: 'clinical_notes',
  CONSENT_INFO: 'consent_info'
};

/**
 * 生成关联ID
 */
const generateCorrelationId = () => {
  return `req_${Date.now()}_${crypto.randomBytes(8).toString('hex')}`;
};

/**
 * 检测PHI数据
 */
const detectPHI = (data, searchText = '') => {
  const phiPatterns = {
    patientId: /\b(patient|mrn|medical\s*record)\s*#?\s*[\w-]+/gi,
    ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
    phone: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g,
    email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
    date: /\b(0[1-9]|1[0-2])[-\/](0[1-9]|[12]\d|3[01])[-\/]\d{4}\b/g,
    medicalTerms: /\b(diagnosis|treatment|medication|prescription|symptom|therapy)\b/gi
  };

  const detectedPHI = [];
  const textToCheck = typeof data === 'string' ? data : JSON.stringify(data) + ' ' + searchText;

  Object.entries(phiPatterns).forEach(([type, pattern]) => {
    const matches = textToCheck.match(pattern);
    if (matches) {
      detectedPHI.push({
        type,
        count: matches.length,
        samples: matches.slice(0, 3) // 只保留前3个样本
      });
    }
  });

  return detectedPHI;
};

/**
 * 敏感数据脱敏
 */
const sanitizePHI = (data, phiDetected = []) => {
  if (!phiDetected.length) return data;

  let sanitized = typeof data === 'string' ? data : JSON.stringify(data);

  phiDetected.forEach(phi => {
    if (phi.type === 'patientId') {
      sanitized = sanitized.replace(/\b(patient|mrn|medical\s*record)\s*#?\s*([\w-]+)/gi, '$1 ***REDACTED***');
    } else if (phi.type === 'ssn') {
      sanitized = sanitized.replace(/\b\d{3}-\d{2}-\d{4}\b/g, '***-**-****');
    } else if (phi.type === 'phone') {
      sanitized = sanitized.replace(/\b(\d{3})[-.]?(\d{3})[-.]?(\d{4})\b/g, '***-***-$3');
    } else if (phi.type === 'email') {
      sanitized = sanitized.replace(/\b([A-Za-z0-9._%+-]+)@([A-Za-z0-9.-]+)\.([A-Z|a-z]{2,})\b/g, '***@***.***');
    }
  });

  return sanitized;
};

/**
 * 创建自定义格式化器
 */
const createCustomFormatter = () => {
  return winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json(),
    winston.format.printf((info) => {
      const logEntry = {
        timestamp: info.timestamp,
        level: info.level,
        correlationId: info.correlationId,
        message: info.message
      };

      // 添加结构化元数据
      if (info.userId) logEntry.userId = info.userId;
      if (info.sessionId) logEntry.sessionId = info.sessionId;
      if (info.action) logEntry.action = info.action;
      if (info.resource) logEntry.resource = info.resource;
      if (info.compliance) logEntry.compliance = info.compliance;
      if (info.security) logEntry.security = info.security;
      if (info.performance) logEntry.performance = info.performance;
      if (info.error) logEntry.error = info.error;
      if (info.metadata) logEntry.metadata = info.metadata;

      // 添加请求上下文
      if (info.request) {
        logEntry.request = {
          method: info.request.method,
          url: info.request.url,
          ip: info.request.ip,
          userAgent: info.request.userAgent
        };
      }

      // 添加审计相关字段
      if (info.level === LogLevel.AUDIT || info.audit) {
        logEntry.audit = {
          eventType: info.audit?.eventType || info.action,
          resourceId: info.audit?.resourceId,
          oldValues: info.audit?.oldValues,
          newValues: info.audit?.newValues,
          reason: info.audit?.reason,
          approvedBy: info.audit?.approvedBy
        };
      }

      return JSON.stringify(logEntry);
    })
  );
};

/**
 * 确保日志目录存在
 */
const ensureLogDirectory = (logDir) => {
  if (!fs.existsSync(logDir)) {
    fs.mkdirSync(logDir, { recursive: true });
  }
};

/**
 * 创建主日志记录器
 */
const createMainLogger = () => {
  const logDir = './logs';
  ensureLogDirectory(logDir);

  return winston.createLogger({
    level: 'debug',
    format: createCustomFormatter(),
    defaultMeta: {
      service: 'endo_sight_uc',
      version: '1.0.0',
      environment: process.env.NODE_ENV || 'development'
    },
    transports: [
      // 控制台输出
      new winston.transports.Console({
        format: winston.format.combine(
          winston.format.colorize(),
          winston.format.simple()
        )
      }),

      // 综合日志文件
      new winston.transports.File({
        filename: path.join(logDir, 'combined.log'),
        maxsize: 50 * 1024 * 1024, // 50MB
        maxFiles: 10,
        tailable: true
      }),

      // 错误日志文件
      new winston.transports.File({
        filename: path.join(logDir, 'error.log'),
        level: 'error',
        maxsize: 20 * 1024 * 1024, // 20MB
        maxFiles: 5
      }),

      // 审计日志文件（不可修改）
      new winston.transports.File({
        filename: path.join(logDir, 'audit.log'),
        level: 'audit',
        maxsize: 100 * 1024 * 1024, // 100MB
        maxFiles: 50,
        tailable: true
      }),

      // 安全日志文件
      new winston.transports.File({
        filename: path.join(logDir, 'security.log'),
        level: 'security',
        maxsize: 30 * 1024 * 1024, // 30MB
        maxFiles: 10
      }),

      // 合规日志文件
      new winston.transports.File({
        filename: path.join(logDir, 'compliance.log'),
        level: 'compliance',
        maxsize: 50 * 1024 * 1024, // 50MB
        maxFiles: 20
      })
    ],

    // 异常处理
    exceptionHandlers: [
      new winston.transports.File({
        filename: path.join(logDir, 'exceptions.log')
      })
    ],

    rejectionHandlers: [
      new winston.transports.File({
        filename: path.join(logDir, 'rejections.log')
      })
    ]
  });
};

/**
 * 创建性能日志记录器
 */
const createPerformanceLogger = () => {
  const logDir = './logs';
  ensureLogDirectory(logDir);

  return winston.createLogger({
    level: 'info',
    format: createCustomFormatter(),
    defaultMeta: {
      service: 'endo_sight_uc_performance',
      type: 'performance'
    },
    transports: [
      new winston.transports.File({
        filename: path.join(logDir, 'performance.log'),
        maxsize: 100 * 1024 * 1024, // 100MB
        maxFiles: 10
      })
    ]
  });
};

// 创建日志记录器实例
const mainLogger = createMainLogger();
const performanceLogger = createPerformanceLogger();

/**
 * 统一结构化日志记录器类
 */
class StructuredLogger {
  constructor() {
    this.mainLogger = mainLogger;
    this.performanceLogger = performanceLogger;
  }

  /**
   * 生成日志ID
   */
  generateLogId() {
    return `log_${Date.now()}_${crypto.randomBytes(8).toString('hex')}`;
  }

  /**
   * 记录一般日志
   */
  log(level, message, meta = {}) {
    const logEntry = {
      level,
      message,
      logId: this.generateLogId(),
      ...meta
    };

    this.mainLogger.log(level, message, logEntry);
  }

  /**
   * 记录关键错误
   */
  critical(message, error = null, meta = {}) {
    this.log(LogLevel.CRITICAL, message, {
      error: error ? {
        name: error.name,
        message: error.message,
        stack: error.stack
      } : null,
      ...meta
    });
  }

  /**
   * 记录错误
   */
  error(message, error = null, meta = {}) {
    this.log(LogLevel.ERROR, message, {
      error: error ? {
        name: error.name,
        message: error.message,
        stack: error.stack
      } : null,
      ...meta
    });
  }

  /**
   * 记录警告
   */
  warning(message, meta = {}) {
    this.log(LogLevel.WARNING, message, meta);
  }

  /**
   * 记录信息
   */
  info(message, meta = {}) {
    this.log(LogLevel.INFO, message, meta);
  }

  /**
   * 记录调试信息
   */
  debug(message, meta = {}) {
    this.log(LogLevel.DEBUG, message, meta);
  }

  /**
   * 记录审计日志（不可修改）
   */
  audit(eventType, message, resource = null, userId = null, meta = {}) {
    const auditEntry = {
      level: LogLevel.AUDIT,
      eventType,
      message,
      userId,
      audit: {
        eventType,
        resourceId: resource?.id,
        resourceType: resource?.type,
        timestamp: new Date().toISOString(),
        ...meta.audit
      },
      ...meta
    };

    // 检测PHI数据
    if (resource || message) {
      const textToCheck = JSON.stringify(resource) + ' ' + message;
      const phiDetected = detectPHI(textToCheck);

      if (phiDetected.length > 0) {
        auditEntry.compliance = {
          phiDetected: true,
          phiTypes: phiDetected.map(p => p.type),
          phiCount: phiDetected.reduce((sum, p) => sum + p.count, 0),
          consentVerified: meta.consent?.verified || false,
          dataSanitized: true
        };
      }
    }

    this.mainLogger.log(LogLevel.AUDIT, message, auditEntry);
  }

  /**
   * 记录安全事件
   */
  security(eventType, message, severity = 'medium', meta = {}) {
    this.log(LogLevel.SECURITY, message, {
      security: {
        eventType,
        severity,
        timestamp: new Date().toISOString(),
        requiresAction: severity === 'high' || severity === 'critical'
      },
      ...meta
    });
  }

  /**
   * 记录合规事件
   */
  compliance(eventType, message, complianceInfo = {}, meta = {}) {
    this.log(LogLevel.COMPLIANCE, message, {
      compliance: {
        eventType,
        regulation: complianceInfo.regulation || 'HIPAA',
        section: complianceInfo.section,
        requirements: complianceInfo.requirements,
        verified: complianceInfo.verified || false,
        timestamp: new Date().toISOString()
      },
      ...meta
    });
  }

  /**
   * 记录性能指标
   */
  performance(operation, duration, metrics = {}, meta = {}) {
    const performanceEntry = {
      operation,
      duration,
      metrics: {
        memory: process.memoryUsage(),
        ...metrics
      },
      performance: {
        operation,
        duration,
        timestamp: new Date().toISOString(),
        slowQuery: duration > (meta.slowThreshold || 1000)
      },
      ...meta
    };

    this.performanceLogger.info(`Performance: ${operation}`, performanceEntry);
  }

  /**
   * 记录HTTP请求
   */
  httpRequest(req, res, duration, meta = {}) {
    this.info('HTTP Request', {
      request: {
        method: req.method,
        url: req.originalUrl || req.url,
        ip: req.ip,
        userAgent: req.get('User-Agent')
      },
      response: {
        statusCode: res.statusCode,
        contentLength: res.get('Content-Length')
      },
      performance: {
        duration,
        slowRequest: duration > 1000
      },
      ...meta
    });
  }

  /**
   * 记录数据库操作
   */
  database(operation, table, duration, result = null, error = null, meta = {}) {
    if (error) {
      this.error(`Database Error: ${operation}`, error, {
        database: {
          operation,
          table,
          duration,
          error: error.message
        },
        ...meta
      });
    } else {
      this.debug(`Database Operation: ${operation}`, {
        database: {
          operation,
          table,
          duration,
          affectedRows: result?.affectedRows || result?.length || 0
        },
        ...meta
      });
    }
  }

  /**
   * 记录AI推理事件
   */
  aiInference(eventType, message, inferenceData = {}, meta = {}) {
    const aiEntry = {
      level: eventType.includes('failure') ? LogLevel.ERROR : LogLevel.INFO,
      message,
      ai: {
        eventType,
        modelVersion: inferenceData.modelVersion,
        confidence: inferenceData.confidence,
        processingTime: inferenceData.processingTime,
        inputHash: inferenceData.inputHash,
        outputHash: inferenceData.outputHash
      },
      ...meta
    };

    this.log(aiEntry.level, message, aiEntry);
  }

  /**
   * 记录用户操作
   */
  userAction(userId, action, resource, details = {}, meta = {}) {
    this.audit(
      `user_${action}`,
      `User ${action} ${resource?.type || 'resource'}`,
      resource,
      userId,
      {
        user: {
          userId,
          action,
          details
        },
        ...meta
      }
    );
  }

  /**
   * 记录医疗数据访问
   */
  medicalDataAccess(userId, patientId, dataType, accessType, reason, meta = {}) {
    this.audit(
      'medical_data_access',
      `Medical data access: ${dataType} - ${accessType}`,
      {
        type: 'patient_data',
        id: patientId
      },
      userId,
      {
        medical: {
          patientId,
          dataType,
          accessType, // 'view', 'modify', 'delete', 'export'
          reason,
          consentVerified: meta.consentVerified || false,
          phiPresent: true
        },
        compliance: {
          phiAccess: true,
          hipaaCompliant: meta.consentVerified || false,
          accessJustification: reason
        },
        ...meta
      }
    );
  }

  /**
   * 创建子日志记录器（带上下文）
   */
  child(context = {}) {
    return {
      critical: (message, error, meta) => this.critical(message, error, { ...context, ...meta }),
      error: (message, error, meta) => this.error(message, error, { ...context, ...meta }),
      warning: (message, meta) => this.warning(message, { ...context, ...meta }),
      info: (message, meta) => this.info(message, { ...context, ...meta }),
      debug: (message, meta) => this.debug(message, { ...context, ...meta }),
      audit: (eventType, message, resource, userId, meta) =>
        this.audit(eventType, message, resource, userId, { ...context, ...meta }),
      security: (eventType, message, severity, meta) =>
        this.security(eventType, message, severity, { ...context, ...meta }),
      compliance: (eventType, message, complianceInfo, meta) =>
        this.compliance(eventType, message, complianceInfo, { ...context, ...meta }),
      performance: (operation, duration, metrics, meta) =>
        this.performance(operation, duration, metrics, { ...context, ...meta }),
      userAction: (userId, action, resource, details, meta) =>
        this.userAction(userId, action, resource, details, { ...context, ...meta }),
      medicalDataAccess: (userId, patientId, dataType, accessType, reason, meta) =>
        this.medicalDataAccess(userId, patientId, dataType, accessType, reason, { ...context, ...meta })
    };
  }
}

// 创建全局结构化日志记录器实例
const structuredLogger = new StructuredLogger();

export default structuredLogger;
export {
  LogLevel,
  AuditEventType,
  PHIDataType,
  generateCorrelationId,
  detectPHI,
  sanitizePHI
};